package luj.tool.jnproxyan.framework.vertx;

import freemarker.template.Configuration;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.templ.freemarker.FreeMarkerTemplateEngine;
import luj.cluster.api.actor.Tellable;
import luj.tool.jnproxyan.proxy.admin.AdminHttpHandler;
import luj.tool.jnproxyan.proxy.admin.AdminHttpMeta;
import luj.tool.jnproxyan.proxy.admin.AdminHttpModule;
import luj.tool.jnproxyan.proxy.admin.http.HttpPathResolver;
import luj.tool.jnproxyan.proxy.admin.http.handle.invoke.HttpHandleInvoker;
import luj.tool.jnproxyan.proxy.start.collect.HttpHandleCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class MainVerticle extends AbstractVerticle {

  public MainVerticle(int port, List<HttpHandleCollector.Kit> handleList, Tellable adminRef) {
    _port = port;
    _handleList = handleList;
    _adminRef = adminRef;
  }

  @Override
  public void start() {
    HttpServer server = vertx.createHttpServer();
    FreeMarkerTemplateEngine freeMarker = useFreeMarker();

    Router router = Router.router(vertx);
    //TODO: 报错处理

    for (HttpHandleCollector.Kit k : _handleList) {
      AdminHttpMeta meta = k.meta();
      String path = new HttpPathResolver(meta).resolve();

      AdminHttpHandler handler = k.handler();
      AdminHttpModule module = meta.module();

//      LOG.debug("{}", path);
      router.route(path).handler(c -> new HttpHandleInvoker(
          handler, c, module, freeMarker, _adminRef).invoke());
    }

    server.requestHandler(router).listen(_port);
  }

  private FreeMarkerTemplateEngine useFreeMarker() {
    FreeMarkerTemplateEngine freeMarker = FreeMarkerTemplateEngine.create(vertx);

    Configuration config = freeMarker.unwrap();
    //TODO: 可能要设置文件目录

    return freeMarker;
  }

  private static final Logger LOG = LoggerFactory.getLogger(MainVerticle.class);

  private final int _port;
  private final List<HttpHandleCollector.Kit> _handleList;

  private final Tellable _adminRef;
}
